package games.snake;

import utils.RandomNumber;
import games.Game;
import hardware.Display2D;
import hardware.UI;

public class Snake2D extends Game {									
	
  	
	
private Snake mySnake = new Snake();
private Apple myApple = new Apple();
private Orange myOrange = new Orange();

private Stone [] myStones;



private int systemSpeed;

private byte[] [] stonePositions = { {-1,-1},{-1,-1},{-1,-1},{-1,-1},
									{0,0},{5,5},{3,7},{5,4},
									{2,2},{3,3},{4,4},{5,5},
									{6,6}};


public Snake2D()
{
	int counter;

	highestSelectableLevel=9;
	gameID=2;
	gameName= "Snake";	

	myStones  = new Stone [4];
	
	for (counter=0;counter<myStones.length;counter++)
		{
		myStones[counter]= new Stone();
		}
	
	
	
	
}

/**
 * Plays Snake demo
 * @return
 * @throws InterruptedException
 */


public int demo() throws InterruptedException
{
	int cmd;
	do{	
		cmd=displayGameName();
		if (cmd==CMD_NONE)
			{
			cmd=playDemo();
			
			if (cmd==CMD_NONE)
				{
				cmd=displayHighscores();		
				}
			}
		
			if (cmd==CMD_SETUP)
			{
				cmd=configGame();	
			}
	}
	while (cmd==CMD_NONE);
	
return(cmd);		
}

/**
 * @author Tavin
 * 
 * Date 28.3.2011
 * 
 * configs snake Game -> level selection
 * 
 * @return key command
 * @throws InterruptedException
 */

public int configGame() throws InterruptedException
{
	int cmd=CMD_NONE;
	int menue=0;
	
	while (true)
		{
		switch (menue)
			{
			case 0:
				cmd=selectLevel();	
			break;

					
			case 1:
				cmd=setupAcc();
				break;
			}
	
		if (cmd==CMD_NEXT)
			menue++;

		if (cmd==CMD_PREV)
			menue--;

		
		if (menue<0)
			menue=1;

		if (menue>2)
			menue=0;

		
		if ((cmd==CMD_SELECT) || (cmd==CMD_ABORT))
				return(cmd);
		}	
}


/**
 * @author Tavin
 * 
 * Date 28.3.2011
 * 
 * plays snake demonstrtion
 */

public int playDemo() throws InterruptedException  
{
	int movieCounter;
	int cmd;
	
	movieCounter=0;
	
	actualLevel=RandomNumber.getRange(8)+1;
	
	prepareLevel();
	
	
	myApple.newApple();
	mySnake.addSegment();


	
	while (true)
	{

	
	
	mySnake.setVector();
	
	if (movieCounter==6)
		{

		mySnake.xPos+=(RandomNumber.getRange(2)-1);
		mySnake.yPos+=(RandomNumber.getRange(2)-1);

	
		mySnake.move();
		movieCounter=0;
	
	
		if ((mySnake.xPos==myApple.xPos) & 
			(mySnake.yPos==myApple.yPos) )
			{
			
			mySnake.addSegment();
			myApple.newApple();
			}
		}
		
		Display2D.clear();
		
		myApple.draw();
		mySnake.draw();

	
		Display2D.doRepaint();
		

		Thread.sleep(100);
	
	movieCounter++;
	
	
	
	
	if (checkForStone(mySnake.xPos,mySnake.yPos)||
			mySnake.checkWallColision() ||
			mySnake.checkInternalColision())
			return (CMD_NONE);	
			
	
	cmd=checkKeys();
	if ((cmd==CMD_SELECT) || (cmd==CMD_ABORT) || (cmd==CMD_PREV) || (cmd==CMD_NEXT)  )
		return(cmd);
	
	}
		
	
}



/**
 * @author Tavin
 * 
 * Date 28.3.2011
 *
 * Play game
 * 
 * @throws InterruptedException
 */


public int  play() throws InterruptedException  
{

	
	actualLevel=beginLevel;
	score=0;
	
	while(true)
	{

	if (UI.keyRUp())
		{
		score+=playLevel();
		displyStatistic();
		displayScore(score);
		
		Thread.sleep(1000);
		
		if (mySnake.getSize()<5)
			return (score);
		actualLevel++;
		}

	if (UI.keyRDown())
			return (score);
		
	
	
	

		Thread.sleep(100);

	}	
}
	
	



public void prepareLevel()
{
	mySnake.init();
	int stoneIndex;
	int counter;
	myOrange.setVisible(false);
	
	systemSpeed=110-(actualLevel*5);
	
	stoneIndex=actualLevel-1;
	if (stoneIndex>=stonePositions.length-4)
		stoneIndex=stonePositions.length-4;
	
		
	
	for (counter=0;counter<myStones.length;counter++)
	{
		myStones[counter].setPos(stonePositions[stoneIndex] [0], stonePositions[stoneIndex] [1]);
		myStones[counter].setVisible(true);
		stoneIndex++;
	}

	
	if (RandomNumber.getRange(2)>0)
		for (counter=0;counter<myStones.length;counter++)
			{
			myStones[counter].mirrorX();
			}
	
	if (RandomNumber.getRange(2)>0)
		for (counter=0;counter<myStones.length;counter++)
			{
			myStones[counter].mirrorY();
			}
	
	
}





public int playLevel() throws InterruptedException  
{
	int movieCounter=0;
	int cycleCounter=0;
	
	int indicatorLed;
	int levelScore=0;

	int tmpCounter;
	
	prepareLevel();
	
	displayLevelNumber();
	
	

	indicatorLed=0;

	do
	{
	myApple.newApple();
	} while ((checkForStone(myApple.xPos,myApple.yPos)) ||
			(myOrange.checkPosition(myApple.xPos,myApple.yPos))|| 
			(mySnake.checkPosition(myApple.xPos,myApple.yPos)));
		
	
	Snake.accXRef=UI.getAccAxis(UI.ACC_AXIS_X);
	Snake.accYRef=UI.getAccAxis(UI.ACC_AXIS_Y);
	
	while (true)
	{
	
	mySnake.setVector();
	
	cycleCounter++;

	
	if (cycleCounter>100)
		{
		if (systemSpeed>20)
			systemSpeed-=5;

		cycleCounter=0;
			
		
		if (indicatorLed<11) //TODO ????
			indicatorLed++;
			
		}
	
	
	
	if (movieCounter==6)
		{
		Display2D.clear();
		
	
		
		mySnake.move();
		movieCounter=0;
	
	
		if (myApple.checkPosition(mySnake.xPos, mySnake.yPos))
			{
			
			mySnake.addSegment();
			levelScore+=(systemSpeed/10)+(actualLevel*2);
			do
			{
			myApple.newApple();
			} while ((checkForStone(myApple.xPos,myApple.yPos)) ||
					(myOrange.checkPosition(myApple.xPos,myApple.yPos))|| 
					(mySnake.checkPresenceAt(myApple.xPos,myApple.yPos)));
			
			
			if (!myOrange.isVisible())
				if (RandomNumber.getRange(10+(actualLevel*2))==1)
					{
					do{
						myOrange.newRandom();
					} while ((checkForStone(myOrange.xPos,myOrange.yPos)) ||
							(myApple.checkPosition(myOrange.xPos,myOrange.yPos))|| 
							(mySnake.checkPresenceAt(myOrange.xPos,myOrange.yPos)));
						
						myOrange.setLifeCounter(20-actualLevel);
					}
						
			}	
			
		
		if (myOrange.checkPosition(mySnake.xPos, mySnake.yPos))
			{
			mySnake.addSegment();
			mySnake.addSegment();
			myOrange.setVisible(false);
			levelScore+=(systemSpeed/10)+(actualLevel*3);
			}
			
	
		for (tmpCounter=0;tmpCounter<myStones.length;tmpCounter++)
			myStones[tmpCounter].draw();
		
		myApple.draw();
		mySnake.draw();
		myOrange.draw();


		
		
		for (int counter=0;counter<indicatorLed;counter++)
			{
			Display2D.setTopLED(counter, (short)0x0f);
			}
		
		Display2D.doRepaint();
		}
	

		Thread.sleep(systemSpeed);
	
	movieCounter++;
	

	if (checkForStone(mySnake.xPos,mySnake.yPos)||
			mySnake.checkWallColision() ||
			mySnake.checkInternalColision())
			return levelScore;
	
	
	}
	

	//return(false);
}




/**
 * @author Tavin
 * 
 * Date 28.3.2011
 * 
 * Display game statistic & points
 */

private void displyStatistic()
{
	Display2D.clear();

	int xPos=0;
	int yPos=0;

	int counter;
	
	counter=0;
	
	Display2D.setPixel((byte)xPos,(byte) yPos, (short)0xf00);
	xPos++;
	while (mySnake.segment[counter]==true)
		{
		Display2D.setPixel((byte)xPos,(byte) yPos, (short)0x850);
		
		xPos++;
		 if (xPos>=Display2D.getColumnCount())
		 	{
			 xPos=0;
			 yPos++;
		 	}
		 if (yPos>=Display2D.getRowCount())
		 	{
			 xPos=0;
			 yPos=0;
		 	}
		 counter++;
		}
	Display2D.doRepaint();
	
	// display Points 
}



/**
 * @author Tavin
 * 
 * Date 1.4.2011
 * 
 * Check for a collision with a stone
 */

public boolean checkForStone(int xPos,int yPos)
{
	int counter;
	
	for (counter=0;counter<myStones.length;counter++)
	{
		if (myStones[counter].checkPosition(xPos, yPos)==true)
			return(true);
	}
	
	
	return(false);
}





}
